package com.sjh.application;

import com.google.auto.service.AutoService;
import com.sjh.application.Application;
import com.sjh.application.Consts;

import java.io.Writer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.JavaFileObject;

import kotlin.Pair;

/**
 * @author Extends
 * @date 2020/6/19
 */
@AutoService(Processor.class)
@SupportedAnnotationTypes(Consts.Application_Annotation_Types)
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class ApplicationProcessor extends AbstractProcessor {

    private Filer filer;
    private ArrayList<Pair<String,String>> mData = new ArrayList<Pair<String,String>>();
    private String moduleName = null;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
        filer = processingEnv.getFiler();

        Map<String, String> options = processingEnvironment.getOptions();
        moduleName = options.get(Consts.MODULE_NAME);
    }

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        if(roundEnvironment == null) return false;
        collectInfo(roundEnvironment);
        for (Pair<String,String> data : mData) {
            writeToFile(Utils.INSTANCE.genCode(moduleName,data.getFirst(),data.getSecond()));
        }
        return true;
    }

    private void collectInfo(RoundEnvironment roundEnvironment){
        Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(Application.class);
        for (Element element : elements) {
            Pair<String,String> pair = new Pair<String,String>(element.getSimpleName().toString(),((TypeElement)element).getQualifiedName().toString());
            mData.add(pair);
        }
    }

    private void writeToFile(Pair<String,String> pair){
        try{
            if(filer == null) return;
            if(mData.isEmpty()) return;

            JavaFileObject file = filer.createSourceFile(pair.getFirst());
            Writer writer = file.openWriter();
            writer.write(pair.getSecond());
            writer.close();

        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public Set<String> getSupportedOptions() {
        return new HashSet<String>(){{
            this.add(Consts.MODULE_NAME);
        }};
    }
}
